﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Security;
using System.Security.Principal;
using System.Text;

[assembly:CLSCompliant(true)]
namespace NetfractionHub
{
	[Flags()]
	public enum IdentityProperties : int
	{
		None,
		SessionId,
		ClientId,
		PrivateId,
		IPv4Address,
		IPv6Address,
		UDPv4Port,
		UDPv6Port,
		ShareSize,
		SharedFilesCount,
		ClientVersionIdentifier,
		MaximumUploadSpeed,
		MaximumDownloadSpeed,
		MaximumUploadSlots,
		AutomaticSlotAllocatorSpeedLimit,
		MinimumUploadConnectionsForAutoSlotAlloc,
		EmailAddress,
		NickOrHubName,
		Description,
		IsNormalUser,
		IsRegisteredUser,
		IsOperator,
		Token,
		ClientType,
		AwayStatus,
		SupportedFeatures,
		RefererUrl
	}

	public class IdentityUpdateEventArgs : EventArgs
	{
		public IdentityUpdateEventArgs(IdentityProperties updatedProperties)
		{
			this.UpdatedProperties = updatedProperties;
		}

		public IdentityProperties UpdatedProperties { get; set; }
	}

	public enum IdentityAwayStatus : int
	{
		Online = 0,
		Away = 1,
		ExtendedAway = 2
	}

	[Flags]
	public enum IdentityNodeTypes : int
	{
		NormalUser = 0,
		Bot = 1,
		RegisteredUser = 2,
		Operator = 4,
		SuperUser = 8,
		HubOwner = 16,
		Hub = 32,
		Hidden = 64
	}

	public class Identity
	{
		public string BroadcastInfoString { get; private set; }

		public void UpdateBroadcastInfoString(string sessionId)
		{
			StringBuilder sb = new StringBuilder("BINF ");
			sb.Append(sessionId);
			sb.Append(' ');

			if (ClientId != string.Empty)
			{
				sb.Append("ID");
				sb.Append(ClientId);
				sb.Append(' ');
			}
			if (Nickname != string.Empty)
			{
				sb.Append("NI");
				sb.Append(Nickname);
				sb.Append(' ');
			}
			if (Email != string.Empty)
			{
				sb.Append("EM");
				sb.Append(Email);
				sb.Append(' ');
			}
			if (Description != string.Empty)
			{
				sb.Append("DE");
				sb.Append(Description);
				sb.Append(' ');
			}
			if (NodeType != IdentityNodeTypes.NormalUser)
			{
				sb.Append("CT");
				sb.Append((int)NodeType);
				sb.Append(' ');
			}
			sb.Append("SL");
			sb.Append(UploadSlots);
			sb.Append(' ');
			sb.Append("SS");
			sb.Append(ShareSize);
			sb.Append(' ');
			sb.Append("SF");
			sb.Append(SharedFilesCount);
			sb.Append(' ');
			sb.Append("AS");
			sb.Append(AutomaticSlotAllocatorSpeedLimit);
			sb.Append(' ');
			sb.Append("AM");
			sb.Append(MinimumUploadConnectionsForAutoSlotAlloc);
			sb.Append(' ');
			sb.Append("VE");
			sb.Append(ClientVersion);
			sb.Append(' ');
			sb.Append("US");
			sb.Append(MaximumUploadSpeed);
			sb.Append(' ');
			sb.Append("DS");
			sb.Append(MaximumDownloadSpeed);
			sb.Append(' ');
			sb.Append("HN");
			sb.Append(HubNormalCount);
			sb.Append(' ');
			sb.Append("HO");
			sb.Append(HubOperatorCount);
			sb.Append(' ');
			sb.Append("HR");
			sb.Append(HubRegisteredCount);
			sb.Append(' ');
			if (AwayStatus != IdentityAwayStatus.Online)
			{
				sb.Append("AW");
				sb.Append((int)AwayStatus);
				sb.Append(' ');
			}
			if (IPv4Address != System.Net.IPAddress.None)
			{
				sb.Append("I4");
				sb.Append(IPv4Address.ToString());
				sb.Append(' ');
			}
			if (Udp4Port > 0)
			{
				sb.Append("U4");
				sb.Append(Udp4Port.ToString());
				sb.Append(' ');
			}
			if (IPv6Address != System.Net.IPAddress.IPv6None)
			{
				sb.Append("I6");
				sb.Append(IPv6Address.ToString());
				sb.Append(' ');
			}
			if (Udp6Port > 0)
			{
				sb.Append("U6");
				sb.Append(Udp6Port.ToString());
				sb.Append(' ');
			}
			if (ClientExtendedFeatures.Count > 0)
			{
				sb.Append("SU");
				sb.Append(string.Join(",", ClientExtendedFeatures));
				sb.Append(' ');
			}
			if (ReferrerUrl != string.Empty)
			{
				sb.Append("RF");
				sb.Append(ReferrerUrl);
			}

			BroadcastInfoString = sb.ToString().Trim();
		}

		public Identity()
		{
			this.ClientExtendedFeatures = new List<string>();
			this.IPv4Address = IPAddress.None;
			this.IPv6Address = IPAddress.IPv6None;
			this.ClientId = string.Empty;
			this.PrivateId = string.Empty;
			this.Nickname = string.Empty;
			this.Password = string.Empty;
			this.Description = string.Empty;
			this.Email = string.Empty;
			this.ClientVersion = string.Empty;
			this.AwayStatus = IdentityAwayStatus.Online;
			this.Token = string.Empty;
			this.ReferrerUrl = string.Empty;
		}

		public override string ToString()
		{
			return string.Empty;
		}

		public bool IsOperator
		{
			get
			{
				return (this.NodeType & IdentityNodeTypes.Operator) == IdentityNodeTypes.Operator;
			}
		}

		public string ClientId { get; set; }
		public string PrivateId { get; set; }
		public string Nickname { get; set; }
		public string Password { get; set; }
		public byte[] PasswordSaltBytes { get; set; }
		public string Description { get; set; }
		public string Email { get; set; }
		public IdentityNodeTypes NodeType { get; set; }
		public int UploadSlots { get; set; }
		public Int64 AutomaticSlotAllocatorSpeedLimit { get; set; }
		public int MinimumUploadConnectionsForAutoSlotAlloc { get; set; }
		public Int64 MaximumUploadSpeed { get; set; }
		public Int64 MaximumDownloadSpeed { get; set; }
		public Int64 ShareSize { get; set; }
		public int SharedFilesCount { get; set; }
		public int HubNormalCount { get; set; }
		public int HubRegisteredCount { get; set; }
		public int HubOperatorCount { get; set; }
		public string ClientVersion { get; set; }
		public IdentityAwayStatus AwayStatus { get; set; }
		public int Udp4Port { get; set; }
		public int Udp6Port { get; set; }
		public List<string> ClientExtendedFeatures { get; set; }
		public IPAddress IPv4Address { get; set; }
		public IPAddress IPv6Address { get; set; }
		public string Token { get; set; }
		public string ReferrerUrl { get; set; }
	}

	public class IdentitySort : System.Collections.IComparer//<Identity>
	{
		#region IComparer<Identity> Members

		public int Compare(object x, object y)
		{
			if (x == null || y == null)
			{
				//throw new ArgumentNullException("Identity Compare");
				return 0;
			}
			Identity xIdent = (x as Identity);
			Identity yIdent = (y as Identity);
			if (xIdent.IsOperator ^ yIdent.IsOperator)
			{
				if (xIdent.IsOperator)
					return -1;
				else
					return 1;
			}

			return string.Compare(xIdent.Nickname, yIdent.Nickname, StringComparison.OrdinalIgnoreCase);
		}

		#endregion
	}
}
